
package net.qiqbframework.common;

import lombok.extern.slf4j.Slf4j;

import java.util.Iterator;
import java.util.ServiceLoader;

/**
 *
 * 
 * @see ServiceLoader
 */
@Slf4j
public abstract class IdentifierFactory {

    private static final IdentifierFactory INSTANCE;

    static {
        log.info("Looking for IdentifierFactory implementation using the context class loader");
        IdentifierFactory factory = locateFactories(Thread.currentThread().getContextClassLoader(), "Context");
        if (factory == null) {
            log.debug("Looking for IdentifierFactory implementation using the IdentifierFactory class loader.");
            factory = locateFactories(IdentifierFactory.class.getClassLoader(), "IdentifierFactory");
        }
        if (factory == null) {
            factory = new DefaultIdFactory();
            log.debug("Using default UUID-based IdentifierFactory");
        } else {
            log.info("Found custom IdentifierFactory implementation: {}", factory.getClass().getName());
        }
        INSTANCE = factory;
    }

    private static IdentifierFactory locateFactories(ClassLoader classLoader, String classLoaderName) {
        IdentifierFactory found = null;
        Iterator<IdentifierFactory> services = ServiceLoader.load(IdentifierFactory.class, classLoader).iterator();
        if (services.hasNext()) {
            log.debug("Found IdentifierFactory implementation using the {} Class Loader", classLoaderName);
            found = services.next();
            if (services.hasNext()) {
                log.warn("More than one IdentifierFactory implementation was found using the {} Class Loader. This may result in different selections being made after restart of the application.", classLoaderName);
            }
        }
        return found;
    }

    public static IdentifierFactory getInstance() {
        return INSTANCE;
    }

    public abstract String generate();
}
